package edu.washington.ling.syntric.io;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import edu.stanford.nlp.util.StringUtils;
import edu.washington.ling.syntric.struct.rule.*;
import edu.washington.ling.syntric.struct.tree.Node;
import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.util.Utils;


public class RuleWriterText extends RuleWriter {
	private String writeToken(Token t) {
		String tag = t.getTag();
		ArrayList<String> fvStrs = new ArrayList<String>();
		for (String feat: t.getFeatures()) {
			if (!t.isDerrived(feat)) {
				fvStrs.add(String.format("%s=%s", feat, t.getValue(feat)));
			}
		}
		return String.format("%s <fs %s>", tag, Utils.join(fvStrs, " "));
	}
	
	private String writeNode(Node n) {
		String label = n.getLabel();
		return label;
	}
	@Override
	public String writeUnaryDSPattern(UniDSPattern dsPatt) {
		Token dsToken = dsPatt.getDSToken();
		return String.format("[%s]", writeToken(dsToken));
	}
	
	private String writeUnaryPSPattern(UniPSPattern psPatt) {
		ArrayList<String> nodeStrs = new ArrayList<String>();
		for (Node psNode: psPatt.getRootChain()) {
			nodeStrs.add(writeNode(psNode));
		}
		return String.format("[%s]", Utils.join(nodeStrs, " "));
	}
	@Override
	public String writeBinaryDSPattern(BiDSPattern dsPatt) {
		String headFinal = "?";
		if (dsPatt.hasHeadOrder()) {
			if (dsPatt.isHeadFinal()) {
				headFinal = "1";
			} else {
				headFinal = "0";
			}
		}
		String dsChildStr = writeToken(dsPatt.getDSDependent());
		String dsParentStr = writeToken(dsPatt.getDSHead());
		return String.format("[%s]\t[%s] %s", dsChildStr, dsParentStr, headFinal);
	}
	
	private String writeBinaryPSPattern(BiPSPattern psPatt) {
		List<String> psRootStrs = new LinkedList<String>();
		for (Node psRootElem: psPatt.getRootChain()) {
			psRootStrs.add(psRootElem.getLabel());
		}
		String psDepChildStr = writeNode(psPatt.getDepChild());
		String psHeadChildStr = writeNode(psPatt.getHeadChild());
		return String.format("(%s (%s %s))", StringUtils.join(psRootStrs, " "), 
				psDepChildStr, psHeadChildStr);
	}
	@Override
	public RuleRepresentation writeBinaryRule(BiRule rule) {
		String dsPattStr = writeBinaryDSPattern(rule.getDSPattern());
		String psPattStr = writeBinaryPSPattern(rule.getPSPattern());
		return new RuleRepresentation(dsPattStr, psPattStr);
	}

	@Override
	public RuleRepresentation writeUnaryRule(UniRule rule) {
		String dsPattStr = writeUnaryDSPattern(rule.getDSPattern());
		String psPattStr = writeUnaryPSPattern(rule.getPSPattern());
		return new RuleRepresentation(dsPattStr, psPattStr);
	}
}
